#include"BitOperation.h"
int copybits(const unsigned char* src,int sbb/*source begin byte*/,int ssb/*source skip bit*/,unsigned char* dest,int dbb/*dest begin byte*/,int dsb/*dest skip bit*/,int nbits)
{
    // assert(src && dest && sbb>=0 && ssb>=0 && dbb>=0 && dsb>=0 && nbits>=0);
    if(src ==NULL || dest == NULL)return -1;
    if(sbb < 0 || ssb < 0 || dbb < 0 || dsb <0)return -2;
    if(nbits==0)return 0;
    if(ssb == dsb){
        //边界对其情况
        //1拷贝对齐部分
        int copybyte=(nbits -(8-ssb))/8;
        memmove(dest+dbb+1,src+sbb+1,copybyte);
        //2拷贝前端不完整字节
        if(ssb != 0){
            unsigned char s=src[sbb];
            s &= 0xFF>>ssb;
            dest[dbb] &= 0xFF<<(8-ssb);
            dest[dbb] |= s;
        }
        //拷贝后端不完整字节
        int endbit=(nbits - (8- ssb))%8;
        if(endbit != 0){
            unsigned char s=src[sbb+1+copybyte];
            s &= 0xFF<<(8-endbit);
            dest[dbb+1 + copybyte] &= 0xFF>>endbit;
            dest[dbb+1 + copybyte] |= s;
        }
        return (8 - endbit);
    }
    //-------------------------------------------------
    int sbgb = sbb*8 + ssb;  //源开始的比特位置
    int dbgb = dbb*8 + dsb;  //目标开始比特位置
    int i;
    int k1,m1,k2,m2;
    unsigned char s;
    if(((dest - src)*8+dbgb) < sbgb  ){
        // 目标开始位置在源开始位置左边
        for(i=0;i<nbits;++i){
            //拷贝某个位
            //1、源位置      目标位置
            k1=(sbgb+i)>>3;    k2=(dbgb+i)>>3;
            m1=(sbgb+i)&0x7;   m2=(dbgb+i)&0x7;
            s=src[k1];
            s &= 0x80>>m1;  //获取源比特位
            if(m1!=m2){  //偏移位
                s = m1<m2? (s>>(m2-m1)):(s<<(m1-m2));
            }
            dest[k2] &= (~(0x80>>m2));  //目标位置0
            dest[k2] |= s;  //目标位赋值
        }
    }
    else{
        for(i=nbits-1; i >=0 ;--i){
            //拷贝某个位
            //1、源位置      目标位置
            k1=(sbgb+i)>>3;    k2=(dbgb+i)>>3;
            m1=(sbgb+i)&0x7;  m2=(dbgb+i)&0x7;
            s=src[k1];
            s &= 0x80>>m1;  //获取源比特位
            if(m1!=m2){  //偏移位
                s = m1<m2? (s>>(m2-m1)):(s<<(m1-m2));
            }
            dest[k2] &= (~(0x80>>m2));  //目标位置0
            dest[k2] |= s;  //目标位赋值
        }
    }
    return (8 - (dbgb+nbits)%8);
}

void BitStream_Attach(wBitStream* bs, BYTE* buffer, UINT32 capacity)
{
    bs->position = 0;
    bs->offset = 0;
    bs->accumulator = 0;
    bs->buffer = buffer;
    bs->pointer = bs->buffer;
    bs->capacity = capacity;
    bs->length = bs->capacity * 8;
}

wBitStream* BitStream_New()
{
    wBitStream* bs = NULL;

    bs = (wBitStream*) calloc(1, sizeof(wBitStream));

    return bs;
}

void BitStream_Free(wBitStream* bs)
{
    free(bs);
}
